﻿/*
 Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.html or http://ckeditor.com/license
 */

CKEDITOR.dialog.add('colordialog', function (editor) {
        // Define some shorthands.
        var $el = CKEDITOR.dom.element,
            $doc = CKEDITOR.document,
            lang = editor.lang.colordialog;

        // Reference the dialog.
        var dialog;

        var spacer =
        {
            type: 'html',
            html: '&nbsp;'
        };

        var selected;

        function clearSelected() {
            $doc.getById(selHiColorId).removeStyle('background-color');
            dialog.getContentElement('picker', 'selectedColor').setValue('');
            selected && selected.removeAttribute('aria-selected');
            selected = null;
        }

        function updateSelected(evt) {
            var target = evt.data.getTarget(),
                color;

            if (target.getName() == 'td' &&
                ( color = target.getChild(0).getHtml() )) {
                selected = target;
                selected.setAttribute('aria-selected', true);
                dialog.getContentElement('picker', 'selectedColor').setValue(color);
            }
        }

        // Basing black-white decision off of luma scheme using the Rec. 709 version
        function whiteOrBlack(color) {
            color = color.replace(/^#/, '');
            for (var i = 0, rgb = []; i <= 2; i++)
                rgb[i] = parseInt(color.substr(i * 2, 2), 16);
            var luma = (0.2126 * rgb[0]) + (0.7152 * rgb[1]) + (0.0722 * rgb[2]);
            return '#' + ( luma >= 165 ? '000' : 'fff' );
        }

        // Distinguish focused and hover states.
        var focused, hovered;

        // Apply highlight style.
        function updateHighlight(event) {
            // Convert to event.
            !event.name && ( event = new CKEDITOR.event(event) );

            var isFocus = !(/mouse/).test(event.name),
                target = event.data.getTarget(),
                color;

            if (target.getName() == 'td' && ( color = target.getChild(0).getHtml() )) {
                removeHighlight(event);

                isFocus ? focused = target : hovered = target;

                // Apply outline style to show focus.
                if (isFocus) {
                    target.setStyle('border-color', whiteOrBlack(color));
                    target.setStyle('border-style', 'dotted');
                }

                $doc.getById(hicolorId).setStyle('background-color', color);
                $doc.getById(hicolorTextId).setHtml(color);
            }
        }

        function clearHighlight() {
            var color = focused.getChild(0).getHtml();
            focused.setStyle('border-color', color);
            focused.setStyle('border-style', 'solid');
            $doc.getById(hicolorId).removeStyle('background-color');
            $doc.getById(hicolorTextId).setHtml('&nbsp;');
            focused = null;
        }

        // Remove previously focused style.
        function removeHighlight(event) {
            var isFocus = !(/mouse/).test(event.name),
                target = isFocus && focused;

            if (target) {
                var color = target.getChild(0).getHtml();
                target.setStyle('border-color', color);
                target.setStyle('border-style', 'solid');
            }

            if (!( focused || hovered )) {
                $doc.getById(hicolorId).removeStyle('background-color');
                $doc.getById(hicolorTextId).setHtml('&nbsp;');
            }
        }

        function onKeyStrokes(evt) {
            var domEvt = evt.data;

            var element = domEvt.getTarget();
            var relative, nodeToMove;
            var keystroke = domEvt.getKeystroke(),
                rtl = editor.lang.dir == 'rtl';

            switch (keystroke) {
                // UP-ARROW
                case 38 :
                    // relative is TR
                    if (( relative = element.getParent().getPrevious() )) {
                        nodeToMove = relative.getChild([element.getIndex()]);
                        nodeToMove.focus();
                    }
                    domEvt.preventDefault();
                    break;
                // DOWN-ARROW
                case 40 :
                    // relative is TR
                    if (( relative = element.getParent().getNext() )) {
                        nodeToMove = relative.getChild([element.getIndex()]);
                        if (nodeToMove && nodeToMove.type == 1) {
                            nodeToMove.focus();
                        }
                    }
                    domEvt.preventDefault();
                    break;

                // SPACE
                // ENTER
                case 32 :
                case 13 :
                    updateSelected(evt);
                    domEvt.preventDefault();
                    break;

                // RIGHT-ARROW
                case rtl ? 37 : 39 :
                    // relative is TD
                    if (( nodeToMove = element.getNext() )) {
                        if (nodeToMove.type == 1) {
                            nodeToMove.focus();
                            domEvt.preventDefault(true);
                        }
                    }
                    // relative is TR
                    else if (( relative = element.getParent().getNext() )) {
                        nodeToMove = relative.getChild([0]);
                        if (nodeToMove && nodeToMove.type == 1) {
                            nodeToMove.focus();
                            domEvt.preventDefault(true);
                        }
                    }
                    break;

                // LEFT-ARROW
                case rtl ? 39 : 37 :
                    // relative is TD
                    if (( nodeToMove = element.getPrevious() )) {
                        nodeToMove.focus();
                        domEvt.preventDefault(true);
                    }
                    // relative is TR
                    else if (( relative = element.getParent().getPrevious() )) {
                        nodeToMove = relative.getLast();
                        nodeToMove.focus();
                        domEvt.preventDefault(true);
                    }
                    break;
                default :
                    // Do not stop not handled events.
                    return;
            }
        }

        function createColorTable() {
            table = CKEDITOR.dom.element.createFromHtml
            (
                '<table tabIndex="-1" aria-label="' + lang.options + '"' +
                ' role="grid" style="border-collapse:separate;" cellspacing="0">' +
                '<caption class="cke_voice_label">' + lang.options + '</caption>' +
                '<tbody role="presentation"></tbody></table>'
            );

            table.on('mouseover', updateHighlight);
            table.on('mouseout', removeHighlight);

            // Create the base colors array.
            var aColors = ['00', '33', '66', '99', 'cc', 'ff'];

            // This function combines two ranges of three values from the color array into a row.
            function appendColorRow(rangeA, rangeB) {
                for (var i = rangeA; i < rangeA + 3; i++) {
                    var row = new $el(table.$.insertRow(-1));
                    row.setAttribute('role', 'row');

                    for (var j = rangeB; j < rangeB + 3; j++) {
                        for (var n = 0; n < 6; n++) {
                            appendColorCell(row.$, '#' + aColors[j] + aColors[n] + aColors[i]);
                        }
                    }
                }
            }

            // This function create a single color cell in the color table.
            function appendColorCell(targetRow, color) {
                var cell = new $el(targetRow.insertCell(-1));
                cell.setAttribute('class', 'ColorCell');
                cell.setAttribute('tabIndex', -1);
                cell.setAttribute('role', 'gridcell');

                cell.on('keydown', onKeyStrokes);
                cell.on('click', updateSelected);
                cell.on('focus', updateHighlight);
                cell.on('blur', removeHighlight);

                cell.setStyle('background-color', color);
                cell.setStyle('border', '1px solid ' + color);

                cell.setStyle('width', '14px');
                cell.setStyle('height', '14px');

                var colorLabel = numbering('color_table_cell');
                cell.setAttribute('aria-labelledby', colorLabel);
                cell.append(CKEDITOR.dom.element.createFromHtml('<span id="' + colorLabel + '" class="cke_voice_label">' + color + '</span>', CKEDITOR.document));
            }

            appendColorRow(0, 0);
            appendColorRow(3, 0);
            appendColorRow(0, 3);
            appendColorRow(3, 3);

            // Create the last row.
            var oRow = new $el(table.$.insertRow(-1));
            oRow.setAttribute('role', 'row');

            // Create the gray scale colors cells.
            for (var n = 0; n < 6; n++) {
                appendColorCell(oRow.$, '#' + aColors[n] + aColors[n] + aColors[n]);
            }

            // Fill the row with black cells.
            for (var i = 0; i < 12; i++) {
                appendColorCell(oRow.$, '#000000');
            }
        }

        var numbering = function (id) {
                return CKEDITOR.tools.getNextId() + '_' + id;
            },
            hicolorId = numbering('hicolor'),
            hicolorTextId = numbering('hicolortext'),
            selHiColorId = numbering('selhicolor'),
            table;

        createColorTable();

        return {
            title: lang.title,
            minWidth: 360,
            minHeight: 220,
            onLoad: function () {
                // Update reference.
                dialog = this;
            },
            onHide: function () {
                clearSelected();
                clearHighlight();
            },
            contents: [
                {
                    id: 'picker',
                    label: lang.title,
                    accessKey: 'I',
                    elements: [
                        {
                            type: 'hbox',
                            padding: 0,
                            widths: ['70%', '10%', '30%'],
                            children: [
                                {
                                    type: 'html',
                                    html: '<div></div>',
                                    onLoad: function () {
                                        CKEDITOR.document.getById(this.domId).append(table);
                                    },
                                    focus: function () {
                                        // Restore the previously focused cell,
                                        // otherwise put the initial focus on the first table cell.
                                        ( focused || this.getElement().getElementsByTag('td').getItem(0) ).focus();
                                    }
                                },
                                spacer,
                                {
                                    type: 'vbox',
                                    padding: 0,
                                    widths: ['70%', '5%', '25%'],
                                    children: [
                                        {
                                            type: 'html',
                                            html: '<span>' + lang.highlight + '</span>\
												<div id="' + hicolorId + '" style="border: 1px solid; height: 74px; width: 74px;"></div>\
												<div id="' + hicolorTextId + '">&nbsp;</div><span>' + lang.selected + '</span>\
												<div id="' + selHiColorId + '" style="border: 1px solid; height: 20px; width: 74px;"></div>'
                                        },
                                        {
                                            type: 'text',
                                            label: lang.selected,
                                            labelStyle: 'display:none',
                                            id: 'selectedColor',
                                            style: 'width: 74px',
                                            onChange: function () {
                                                // Try to update color preview with new value. If fails, then set it no none.
                                                try {
                                                    $doc.getById(selHiColorId).setStyle('background-color', this.getValue());
                                                }
                                                catch (e) {
                                                    clearSelected();
                                                }
                                            }
                                        },
                                        spacer,
                                        {
                                            type: 'button',
                                            id: 'clear',
                                            style: 'margin-top: 5px',
                                            label: lang.clear,
                                            onClick: clearSelected
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                }
            ]
        };
    }
);
